#include "variables.hpp"
#include <cstdlib>
#include <cstdio>

Variable::Variable(void)
{
	i = 0;
	str = "";
	type = tNull;
}

Variable::Variable(double d)
{
	i = d;
	char tmp[128]; // Precision can't get this large anyways...
	sprintf(tmp, "%g", i);
	str = tmp;
	type = tNumeric;
}

Variable::Variable(string s)
{
	str = s;
	i = atoi(str.c_str());
	type = tString;
}

Variable::~Variable()
{
	// Nothing here...
}

Variable*  Variable::clear()
{
	arr.clear();
	str="";
	type=tNull;
	i=0;
	return this;
}

Variable*  Variable::makearr(int count)
{
	if(count==0) {
		arr.clear();
	} else {
		arr.resize(count);
	}
	type = tArray;
	return this;
}

void Variable::tell(void)
{
	cout << "`" << str << "`/" << i << "\n";
	cout << "\t" << arr.size() << " elements\n";
	cout << "\t" << vartypeToStr(type) << "\n";
}

bool checkconditional(double a, string op, double b)
{
	if(op=="==") {
		return(a==b);
	} else if(op==">") {
		return(a>b);
	} else if(op==">=") {
		return(a>=b);
	} else if(op=="<") {
		return(a<b);
	} else if(op=="<=") {
		return(a<=b);
	} else if(op=="!=") {
		return(a!=b);
	}
	throw_error(ERROR_OPERATION);
}

bool checkconditional(string a, string op, string b)
{
	if(op=="==") {
		return(a==b);
	} else if(op==">") {
		return(a>b);
	} else if(op==">=") {
		return(a>=b);
	} else if(op=="<") {
		return(a<b);
	} else if(op=="<=") {
		return(a<=b);
	} else if(op=="!=") {
		return(a!=b);
	}
	throw_error(ERROR_OPERATION);
}

bool isspecialchar(char c)
{
	return (
		(c=='?') ||
		(c==';') ||
		(c==',') ||
		(c=='[') ||
		(c==']') ||
		(c=='~') ||
		(c=='@') ||
		(c=='#') ||
		(c=='$') ||
		(c=='\\')
	);
}
bool isSettingOpcode(string s)
{
	return (
		(s=="=") ||	
		(s=="+=") ||
		(s=="-=") ||
		(s=="*=") ||
		(s=="/=") ||
		(s=="%=") ||
		(s=="^=") ||
		(s=="|=") ||
		(s=="&=") ||
		(s=="**=")
	);
}

bool isopcode(string s)
{
	return (
		isSettingOpcode(s) ||
		(s=="+") ||
		(s=="-") ||
		(s=="*") ||
		(s=="/") ||
		(s=="%") ||
		(s=="^") ||
		(s==">") ||
		(s=="<") ||
		(s=="|") ||
		(s=="&") ||
		(s=="**") ||
		(s=="==") ||
		(s=="!=") ||
		(s==">=") ||
		(s=="<=")
	);
}

bool isopcode(char c)
{
	return (
		(c=='=') ||
		(c=='+') ||
		(c=='-') ||
		(c=='*') ||
		(c=='/') ||
		(c=='%') ||
		(c=='^') ||
		(c=='>') ||
		(c=='<') ||
		(c=='!') ||
		(c=='|') ||
		(c=='&')
	);
}

bool isalpha(char c)
{
	return ((c>='A' && c<='Z') || (c>='a' && c<='z'));
}

bool islegalvarnamestarter(char c)
{
	return (isalpha(c) || c == '_');
}

bool islegalvarname(char c)
{
	return (isalphanumeric(c,false) || c == '_' || c == ':' || c == '$');
}

bool isDecNumeric(char c, bool neg)
{
	if(neg && c=='.') {
		return true;
	}
	return ( (c >= '0') && (c <= '9') );
}

bool isOctNumeric(char c, bool neg)
{
	if(neg && c=='.') {
		return true;
	}
	return ( (c >= '0') && (c <= '7') );
}

bool isHexNumeric(char c, bool neg)
{
	if(neg && c=='.') {
		return true;
	}
	return ( ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')) );
}

bool isBinNumeric(char c, bool neg)
{
	return (c == '0' || c == '1' || (neg && c=='.'));
}

bool isalphanumeric(char c, bool space)
{
	if(space && c==' ') {
		return true;
	}
	return (isalpha(c)||isDecNumeric(c,false));
}

string trim_le_whitespace(string str)
{
	size_t pos = str.find_first_not_of(" \t\n\r");
	string ret = str.substr(pos,str.find_last_not_of(" \t\n\r")+1-pos);
	return ret;
}

string vartypeToStr(Vartype v)
{
	switch(v) {
		case tNull:
			return "Null";
			break;
		case tFunction:
			return "Function";
			break;
		case tOpcode:
			return "Opcode";
			break;
		case tVarname:
			return "Variable name";
			break;
		case tNumeric:
			return "Number";
			break;
		case tString:
			return "String";
			break;
		case tAlias:
			return "Alias";
			break;
		case tInline:
			return "Inline code";
			break;
		case tArray:
			return "Array";
			break;
		case tReference:
			return "Reference";
			break;
		case tError:
			return "Error";
			break;
		case tSpecial:
			return "Special Character";
			break;
		case tTypeID:
			return "Type ID";
			break;
		case tCustomType:
			return "Custom Type";
			break;
		case tUnknown:
		default:
			return "Unknown";
			break;
	}
}
